// SPDX-License-Identifier: GPL-2.0

/**
 * Copyright (C) 2025 Huawei Technologies Co., Ltd.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, see <https://www.gnu.org/licenses/>.
 *
 * @file hw_regs_access.c
 * @brief Hisilicon HW registers access related implementations
 * @details The kernel driver implementation for Hisilicon HW registers accessing,
 * which is used by Kunpeng Cache Management Framework.
 */
#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__

#include <linux/io.h>

#include "hw_regs_access.h"

/**
 * Definition for core registers READ functions implementation
 */
#define READ_CORE_REG_FUNC(reg, name)                 \
    u64 cman_drv_##name##_read(void)                  \
	{                                                 \
		u64 val = 0;                                  \
		asm volatile("dsb sy" ::: "memory");          \
		asm volatile("isb" ::: "memory");             \
		asm volatile("MRS %0, " #reg "" : "=r"(val)); \
		asm volatile("isb" ::: "memory");             \
		return val;                                   \
	}

/**
 * Definition for core registers WRITE functions implementation
 */
#define WRITE_CORE_REG_FUNC(reg, name)              \
    bool cman_drv_##name##_write(u64 val)           \
	{                                               \
		u64 read_val;                               \
		asm volatile("dsb sy" ::: "memory");        \
		asm volatile("isb" ::: "memory");           \
		asm volatile("MSR " #reg ",%0" ::"r"(val)); \
		asm volatile("isb" ::: "memory");           \
		asm volatile("dsb sy" ::: "memory");        \
		read_val = cman_drv_##name##_read();        \
		return read_val == val;                     \
	}

READ_CORE_REG_FUNC(S3_1_c0_c0_0, ccsidr_el1)
WRITE_CORE_REG_FUNC(S3_1_c0_c0_0, ccsidr_el1)
READ_CORE_REG_FUNC(S3_1_c0_c0_2, ccsidr2_el1)
WRITE_CORE_REG_FUNC(S3_1_c0_c0_2, ccsidr2_el1)
READ_CORE_REG_FUNC(S3_2_c0_c0_0, csselr_el1)
WRITE_CORE_REG_FUNC(S3_2_c0_c0_0, csselr_el1)
READ_CORE_REG_FUNC(S3_1_c15_c5_2, l2_partition_reg)
WRITE_CORE_REG_FUNC(S3_1_c15_c5_2, l2_partition_reg)
READ_CORE_REG_FUNC(S3_0_c0_c7_2, memory_model_feature_reg)
WRITE_CORE_REG_FUNC(S3_0_c0_c7_2, memory_model_feature_reg)
